﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using Autodesk.Revit.ApplicationServices;
using Autodesk.Revit.Attributes;
using Autodesk.Revit.DB;
using Autodesk.Revit.DB.Plumbing;
using Autodesk.Revit.Exceptions;
using Autodesk.Revit.UI;
using YArchitech.HVAC;
using YArchitech.LIB;
using YArchitech.Revit;

namespace YArchitech.Plumbing
{
	[Transaction(TransactionMode.Manual)]
	[Regeneration(RegenerationOption.Manual)]
	public class ThwartwiseCreate : IExternalCommand
	{
		[DllImport("user32.dll", EntryPoint = "SendMessageA")]
		public static extern int SendMessage(IntPtr hwnd, int wMsg, IntPtr wParam, IntPtr lParam);

		private XYZ getxyz(Pipe pipe)
		{
			Line curve = (pipe.Location as LocationCurve).Curve as Line;
			return (curve.GetEndPoint(0) + curve.GetEndPoint(1)) / 2.0;
		}

		public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
		{
			Transaction transaction = null;
			UIApplication application = commandData.Application;
			Autodesk.Revit.ApplicationServices.Application application2 = application.Application;
			Document document = application.ActiveUIDocument.Document;
			UIDocument activeUIDocument = commandData.Application.ActiveUIDocument;
			List<string> levelUp = new List<string>();
			levelUp = YJKElementFilter.GetElementNameByClass(typeof(Level), document);
			List<string> pipeType = new List<string>();
			pipeType = YJKElementFilter.GetElementNameByClass(typeof(PipeType), document);
			List<string> pipingSystemType = new List<string>();
			pipingSystemType = YJKElementFilter.GetElementNameByClass(typeof(PipingSystemType), document);
			new HYPipeConnect();
			List<ViewType> viewTypes = YJKRevitTools.ListViewNeed(1);
			if (!YJKRevitTools.ViewCheck(activeUIDocument, viewTypes))
			{
				return Autodesk.Revit.UI.Result.Cancelled;
			}
			if (ThwartwiseCreate.hWndRevit == null)
			{
				ThwartwiseCreate.hWndRevit = new YJKWindowHandle(Process.GetCurrentProcess().MainWindowHandle);
			}
			FormCreateThwartwisePipe formCreateThwartwisePipe = new FormCreateThwartwisePipe(document, levelUp, pipeType, pipingSystemType);
			formCreateThwartwisePipe.Show(ThwartwiseCreate.hWndRevit);
			int wMsg = 7;
			ThwartwiseCreate.SendMessage(ThwartwiseCreate.hWndRevit.Handle, wMsg, IntPtr.Zero, IntPtr.Zero);
			Result result;
			for (;;)
			{
				try
				{
					XYZ xyz = activeUIDocument.Selection.PickPoint("请选择绘制横管所基于线的起点（坡度将以该点为起点）...");
					XYZ xyz2 = null;
					if (xyz != null)
					{
						Pipe pipe = null;
						Pipe pipe2 = null;
						for (;;)
						{
							transaction = new Transaction(document, "绘制横管");
							transaction.Start();
							try
							{
								if (formCreateThwartwisePipe.Visible)
								{
									using (PipeCreateJigPolarAxis pipeCreateJigPolarAxis = new PipeCreateJigPolarAxis(activeUIDocument))
									{
										pipeCreateJigPolarAxis.StartPoint = xyz;
										pipeCreateJigPolarAxis.DrawSize = true;
                                        System.Windows.Forms.Application.DoEvents();
										pipeCreateJigPolarAxis.SetPromptState("", false, "", true);
										xyz2 = pipeCreateJigPolarAxis.PickEndPoint(xyz, "请选择绘制横管所基于线的终点...");
										pipeCreateJigPolarAxis.Dispose();
									}
									if (xyz2 == null)
									{
										break;
									}
									if (xyz2.IsAlmostEqualTo(xyz))
									{
										MessageBox.Show("选择的两点过于接近，无法创建！", "盈建科提示", MessageBoxButtons.OK, MessageBoxIcon.Asterisk);
										break;
									}
									double levelOffset = double.Parse(formCreateThwartwisePipe.textBoxLevel.Text) * 1000.0 + document.ActiveView.GenLevel.ProjectElevation * 304.8;
									double offset = double.Parse(formCreateThwartwisePipe.textBoxOffset.Text);
									PipeType pipeType2 = formCreateThwartwisePipe.Get_PipeType(document, formCreateThwartwisePipe.comboBoxPipeClass.Text);
									PipingSystemType pipingSystemType2 = formCreateThwartwisePipe.Get_PipingSystemType(document, formCreateThwartwisePipe.comboBoxPipingSystemType.Text);
									string text = formCreateThwartwisePipe.comboBoxPipeDiameter.Text;
									double slope;
									if (formCreateThwartwisePipe.hyTextBox1.Visible)
									{
										slope = double.Parse(formCreateThwartwisePipe.hyTextBox1.Text);
									}
									else
									{
										slope = 0.0;
									}
									XYZ newXYZDeriction = YJKRevitTools.getNewXYZDeriction(xyz, xyz2);
									HYCreatePipeHelper hycreatePipeHelper = new HYCreatePipeHelper();
									if (newXYZDeriction != null)
									{
										pipe2 = hycreatePipeHelper.DrawThwartwisePipe(document, offset, levelOffset, xyz, xyz2, pipeType2, double.Parse(text), pipingSystemType2, slope, newXYZDeriction);
									}
									Line curve = (pipe2.Location as LocationCurve).Curve as Line;
									formCreateThwartwisePipe.textBoxLevel.Text = Math.Round((curve.GetEndPoint(1).Z - document.ActiveView.GenLevel.ProjectElevation) * 0.3048, 3).ToString();
									xyz = xyz2;
									xyz2 = null;
									if (pipe != null && pipe.IsValidObject && pipe2 != null)
									{
										Line line = (pipe.Location as LocationCurve).Curve as Line;
										Line line2 = (pipe2.Location as LocationCurve).Curve as Line;
										YJKLine YJKLine = new YJKLine(line);
										YJKLine YJKLine2 = new YJKLine(line2);
										if (!YJKLine.IsLineOnLine(line2) && !YJKLine.IsXYParallel(line2))
										{
											XYZ xyz3 = (YJKLine.EndPoint - YJKLine.StartPoint).Normalize();
											XYZ xyz4 = (YJKLine2.EndPoint - YJKLine2.StartPoint).Normalize();
											YJKPipeConnectorHelper hypipeConnectorHelper = new YJKPipeConnectorHelper();
											if ((Math.Abs(xyz3.X) < 1E-06 && Math.Abs(xyz4.Y) < 1E-06) || (Math.Abs(xyz3.Y) < 1E-06 && Math.Abs(xyz4.X) < 1E-06))
											{
												if (!hypipeConnectorHelper.pipeconnectpipeForPolarAxis(pipe, this.getxyz(pipe), pipe2, this.getxyz(pipe2), document))
												{
													MessageBox.Show("没有可以使用的族配置，请检查Revit的族配置", "盈建科提示", MessageBoxButtons.OK, MessageBoxIcon.Asterisk);
													transaction.RollBack();
													break;
												}
											}
											else if (xyz3.AngleTo(xyz4) * 180.0 / Math.PI <= 90.0)
											{
												if (!hypipeConnectorHelper.pipeconnectpipeForPolarAxis(pipe, this.getxyz(pipe), pipe2, this.getxyz(pipe2), document))
												{
													MessageBox.Show("没有可以使用的族配置，请检查Revit的族配置", "盈建科提示", MessageBoxButtons.OK, MessageBoxIcon.Asterisk);
													transaction.RollBack();
													break;
												}
											}
											else
											{
												hypipeConnectorHelper.connect45Elbow(pipe, this.getxyz(pipe), pipe2, this.getxyz(pipe2), document);
											}
										}
									}
									pipe = pipe2;
								}
							}
							catch (Autodesk.Revit.Exceptions.OperationCanceledException)
							{
								pipe = null;
								transaction.RollBack();
								break;
							}
							document.Regenerate();
							transaction.Commit();
						}
						continue;
					}
					formCreateThwartwisePipe.Close();
					result = Autodesk.Revit.UI.Result.Succeeded;
				}
				catch (Autodesk.Revit.Exceptions.OperationCanceledException)
				{
					formCreateThwartwisePipe.Close();
					result = Autodesk.Revit.UI.Result.Succeeded;
				}
				catch (Exception ex)
				{
					if (ex.Message.Contains("Fitting cannot be created between the input connectors because the angle between them is too small or too large."))
					{
						MessageBox.Show("您绘制管道与上一次绘制管道夹角过大或过小！", "盈建科提示", MessageBoxButtons.OK, MessageBoxIcon.Asterisk);
					}
					else if (ex.Message.Contains("failed to insert elbow."))
					{
						MessageBox.Show("没有可以使用的族配置，请检查Revit的族配置", "盈建科提示", MessageBoxButtons.OK, MessageBoxIcon.Asterisk);
					}
					else
					{
						MessageBox.Show(ex.Message, "盈建科提示", MessageBoxButtons.OK, MessageBoxIcon.Asterisk);
					}
					this.EndTransation(transaction, false);
					formCreateThwartwisePipe.Close();
					result = Autodesk.Revit.UI.Result.Succeeded;
				}
				finally
				{
					this.EndTransation(transaction, true);
				}
				break;
			}
			return result;
		}

		private void EndTransation(Transaction tran, bool beSure)
		{
			if (tran != null)
			{
				TransactionStatus status = tran.GetStatus();
				if ((int)status == 1)
				{
					if (beSure)
					{
						tran.Commit();
						return;
					}
					tran.RollBack();
					return;
				}
				else if ((int)status == 5)
				{
					tran.RollBack();
				}
			}
		}

		public static YJKWindowHandle hWndRevit;
	}
}
